package v1

import (
	"chat/models"
	"chat/pkg/utils"
	"encoding/json"
	"log"
	"net/http"
	"sync"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

var (
	// 用于升级HTTP连接为WebSocket连接
	upgrader = websocket.Upgrader{
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	// 保存所有在线用户的WebSocket连接
	clients = make(map[uint]*websocket.Conn)
	// 保护clients map的互斥锁
	clientsMutex sync.RWMutex
)

// MessageType 消息类型
type MessageType int

const (
	TextMessage MessageType = iota
	SystemMessage
)

// Message WebSocket消息结构
type Message struct {
	Type       MessageType `json:"type"`
	Content    string      `json:"content"`
	From       uint        `json:"from"`
	SenderName string      `json:"sender_name"`
	Timestamp  time.Time   `json:"timestamp"`
}

// HandleWebSocket 处理WebSocket连接
func HandleWebSocket(c *gin.Context) {
	// 从上下文中获取用户ID
	userID := c.GetUint("userID")
	if userID == 0 {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未授权"})
		return
	}

	// 获取用户信息
	var user models.User
	if err := utils.DB.First(&user, userID).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取用户信息失败"})
		return
	}

	// 升级HTTP连接为WebSocket连接
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		log.Printf("升级WebSocket连接失败: %v", err)
		return
	}

	// 将新用户的WebSocket连接保存到clients map中
	clientsMutex.Lock()
	clients[userID] = conn
	clientsMutex.Unlock()

	// 广播用户上线消息
	broadcastMessage(Message{
		Type:       SystemMessage,
		Content:    "用户上线",
		From:       userID,
		SenderName: user.Nickname,
		Timestamp:  time.Now(),
	})

	// 确保连接关闭时清理资源
	defer func() {
		clientsMutex.Lock()
		delete(clients, userID)
		clientsMutex.Unlock()
		conn.Close()

		// 广播用户下线消息
		broadcastMessage(Message{
			Type:       SystemMessage,
			Content:    "用户下线",
			From:       userID,
			SenderName: user.Nickname,
			Timestamp:  time.Now(),
		})
	}()

	// 处理接收到的消息
	for {
		_, msgBytes, err := conn.ReadMessage()
		if err != nil {
			if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
				log.Printf("WebSocket错误: %v", err)
			}
			break
		}

		// 解析消息
		var msg Message
		if err := json.Unmarshal(msgBytes, &msg); err != nil {
			log.Printf("解析消息失败: %v", err)
			continue
		}

		// 设置消息的发送者和时间戳
		msg.From = userID
		msg.SenderName = user.Nickname
		if msg.SenderName == "" {
			msg.SenderName = user.Username
		}
		msg.Timestamp = time.Now()

		// 保存消息到数据库
		dbMsg := models.Message{
			FromUserID: userID,
			Content:    msg.Content,
			Type:       int(msg.Type),
		}
		if err := utils.DB.Create(&dbMsg).Error; err != nil {
			log.Printf("保存消息失败: %v", err)
			continue
		}

		// 广播消息给所有在线用户
		broadcastMessage(msg)
	}
}

// broadcastMessage 广播消息给所有在线用户
func broadcastMessage(msg Message) {
	msgBytes, err := json.Marshal(msg)
	if err != nil {
		log.Printf("序列化消息失败: %v", err)
		return
	}

	clientsMutex.RLock()
	defer clientsMutex.RUnlock()

	for _, conn := range clients {
		if err := conn.WriteMessage(websocket.TextMessage, msgBytes); err != nil {
			log.Printf("发送消息失败: %v", err)
		}
	}
}
